<script setup lang="ts">
import { reactive, watch } from 'vue';
import { NButton, NCard, NColorPicker, NForm, NFormItem, NInputNumber, NSelect, NSpace } from 'naive-ui';

interface StyleConfig {
  theme: {
    primaryColor: string;
    secondaryColor: string;
    accentColor: string;
    backgroundColor: string;
    surfaceColor: string;
  };
  typography: {
    fontFamily: string;
    baseFontSize?: number;
    headingScale?: number;
    lineHeight?: number;
    letterSpacing?: number;
  };
  layout: {
    borderRadius?: number;
    spacing?: number;
    maxWidth?: number;
    gridGap?: number;
  };
  components: {
    buttonStyle: 'filled' | 'outlined' | 'ghost';
    cardElevation?: number;
    inputStyle: 'underline' | 'outline' | 'filled';
  };
}

interface Props {
  styleConfig: StyleConfig;
  presetStyles: Array<{ name: string; value: string }>;
}

const props = defineProps<Props>();

const emit = defineEmits<{
  (e: 'update:styleConfig', config: StyleConfig): void;
  (e: 'apply-preset', preset: string): void;
  (e: 'randomize'): void;
}>();

// Create a local reactive copy to avoid direct mutation of props
const localStyleConfig = reactive<StyleConfig>({
  ...props.styleConfig
});

// Watch for prop changes and update local copy
watch(
  () => props.styleConfig,
  newConfig => {
    Object.assign(localStyleConfig, newConfig);
  },
  { deep: true }
);

const fontOptions = [
  { label: 'Inter', value: 'Inter' },
  { label: 'Arial', value: 'Arial' },
  { label: 'Georgia', value: 'Georgia' },
  { label: 'Monaco', value: 'Monaco' },
  { label: 'Times New Roman', value: 'Times New Roman' },
  { label: 'Helvetica', value: 'Helvetica' }
];

const buttonStyleOptions = [
  { label: '填充', value: 'filled' },
  { label: '轮廓', value: 'outlined' },
  { label: '幽灵', value: 'ghost' }
];

const inputStyleOptions = [
  { label: '下划线', value: 'underline' },
  { label: '轮廓', value: 'outline' },
  { label: '填充', value: 'filled' }
];

function updateStyleConfig(updates: Partial<StyleConfig>) {
  const newConfig = { ...localStyleConfig, ...updates };
  Object.assign(localStyleConfig, newConfig);
  emit('update:styleConfig', newConfig);
}

function updateTheme(updates: Partial<StyleConfig['theme']>) {
  const newTheme = { ...localStyleConfig.theme, ...updates };
  localStyleConfig.theme = newTheme;
  updateStyleConfig({ ...localStyleConfig, theme: newTheme });
}

function updateTypography(
  updates: Partial<
    StyleConfig['typography'] & {
      baseFontSize?: number | null;
      headingScale?: number | null;
      lineHeight?: number | null;
      letterSpacing?: number | null;
    }
  >
) {
  // Handle null values from NInputNumber by converting to undefined
  const sanitizedUpdates = Object.fromEntries(
    Object.entries(updates).map(([key, value]) => {
      if (value === null) {
        return [key, undefined];
      }
      return [key, value];
    })
  ) as Partial<StyleConfig['typography']>;

  const newTypography = { ...localStyleConfig.typography, ...sanitizedUpdates };
  localStyleConfig.typography = newTypography;
  updateStyleConfig({ ...localStyleConfig, typography: newTypography });
}

function updateLayout(
  updates: Partial<
    StyleConfig['layout'] & {
      borderRadius?: number | null;
      spacing?: number | null;
      maxWidth?: number | null;
      gridGap?: number | null;
    }
  >
) {
  // Handle null values from NInputNumber by converting to undefined
  const sanitizedUpdates = Object.fromEntries(
    Object.entries(updates).map(([key, value]) => {
      if (value === null) {
        return [key, undefined];
      }
      return [key, value];
    })
  ) as Partial<StyleConfig['layout']>;

  const newLayout = { ...localStyleConfig.layout, ...sanitizedUpdates };
  localStyleConfig.layout = newLayout;
  updateStyleConfig({ ...localStyleConfig, layout: newLayout });
}

function updateComponents(
  updates: Partial<
    StyleConfig['components'] & {
      cardElevation?: number | null;
    }
  >
) {
  // Handle null values from NInputNumber by converting to undefined
  const sanitizedUpdates = Object.fromEntries(
    Object.entries(updates).map(([key, value]) => {
      if (value === null) {
        return [key, undefined];
      }
      return [key, value];
    })
  ) as Partial<StyleConfig['components']>;

  const newComponents = { ...localStyleConfig.components, ...sanitizedUpdates };
  localStyleConfig.components = newComponents;
  updateStyleConfig({ ...localStyleConfig, components: newComponents });
}

function toUndefined<T>(value: T | null): T | undefined {
  return value === null ? undefined : value;
}
</script>

<template>
  <NScrollbar class="style-configurator">
    <!-- Preset Styles -->
    <NCard title="预设风格" size="small" class="mb-12px">
      <NSpace wrap :size="8">
        <NButton
          v-for="preset in presetStyles"
          :key="preset.value"
          size="small"
          @click="emit('apply-preset', preset.value)"
        >
          {{ preset.name }}
        </NButton>
        <NButton type="primary" size="small" @click="emit('randomize')">🎲 随机生成</NButton>
      </NSpace>
    </NCard>

    <!-- Theme Configuration -->
    <NCard title="主题色彩" size="small" class="mb-12px">
      <NForm :show-label="true" label-placement="left" label-width="80px">
        <NFormItem label="主色调">
          <NColorPicker
            :value="localStyleConfig.theme.primaryColor"
            :show-alpha="false"
            @update:value="updateTheme({ primaryColor: $event })"
          />
        </NFormItem>
        <NFormItem label="辅助色">
          <NColorPicker
            :value="localStyleConfig.theme.secondaryColor"
            :show-alpha="false"
            @update:value="updateTheme({ secondaryColor: $event })"
          />
        </NFormItem>
        <NFormItem label="强调色">
          <NColorPicker
            :value="localStyleConfig.theme.accentColor"
            :show-alpha="false"
            @update:value="updateTheme({ accentColor: $event })"
          />
        </NFormItem>
        <NFormItem label="背景色">
          <NColorPicker
            :value="localStyleConfig.theme.backgroundColor"
            :show-alpha="false"
            @update:value="updateTheme({ backgroundColor: $event })"
          />
        </NFormItem>
        <NFormItem label="表面色">
          <NColorPicker
            :value="localStyleConfig.theme.surfaceColor"
            :show-alpha="false"
            @update:value="updateTheme({ surfaceColor: $event })"
          />
        </NFormItem>
      </NForm>
    </NCard>

    <!-- Typography Configuration -->
    <NCard title="字体排版" size="small" class="mb-12px">
      <NForm :show-label="true" label-placement="left" label-width="80px">
        <NFormItem label="字体族">
          <NSelect
            :value="localStyleConfig.typography.fontFamily"
            :options="fontOptions"
            @update:value="updateTypography({ fontFamily: $event })"
          />
        </NFormItem>
        <NFormItem label="基础字号">
          <NInputNumber
            :value="localStyleConfig.typography.baseFontSize"
            :min="12"
            :max="24"
            @update:value="updateTypography({ baseFontSize: toUndefined($event) })"
          >
            <template #suffix>px</template>
          </NInputNumber>
        </NFormItem>
        <NFormItem label="标题缩放">
          <NInputNumber
            :value="localStyleConfig.typography.headingScale"
            :min="1"
            :max="2"
            :step="0.1"
            @update:value="updateTypography({ headingScale: toUndefined($event) })"
          />
        </NFormItem>
        <NFormItem label="行高">
          <NInputNumber
            :value="localStyleConfig.typography.lineHeight"
            :min="1"
            :max="3"
            :step="0.1"
            @update:value="updateTypography({ lineHeight: toUndefined($event) })"
          />
        </NFormItem>
        <NFormItem label="字间距">
          <NInputNumber
            :value="localStyleConfig.typography.letterSpacing || undefined"
            :min="-2"
            :max="5"
            @update:value="updateTypography({ letterSpacing: toUndefined($event) })"
          >
            <template #suffix>px</template>
          </NInputNumber>
        </NFormItem>
      </NForm>
    </NCard>

    <!-- Layout Configuration -->
    <NCard title="布局设置" size="small" class="mb-12px">
      <NForm :show-label="true" label-placement="left" label-width="80px">
        <NFormItem label="圆角半径">
          <NInputNumber
            :value="localStyleConfig.layout.borderRadius"
            :min="0"
            :max="50"
            @update:value="updateLayout({ borderRadius: toUndefined($event) })"
          >
            <template #suffix>px</template>
          </NInputNumber>
        </NFormItem>
        <NFormItem label="间距">
          <NInputNumber
            :value="localStyleConfig.layout.spacing"
            :min="4"
            :max="64"
            @update:value="updateLayout({ spacing: toUndefined($event) })"
          >
            <template #suffix>px</template>
          </NInputNumber>
        </NFormItem>
        <NFormItem label="最大宽度">
          <NInputNumber
            :value="localStyleConfig.layout.maxWidth"
            :min="600"
            :max="2000"
            :step="100"
            @update:value="updateLayout({ maxWidth: toUndefined($event) })"
          >
            <template #suffix>px</template>
          </NInputNumber>
        </NFormItem>
        <NFormItem label="网格间距">
          <NInputNumber
            :value="localStyleConfig.layout.gridGap"
            :min="8"
            :max="64"
            @update:value="updateLayout({ gridGap: toUndefined($event) })"
          >
            <template #suffix>px</template>
          </NInputNumber>
        </NFormItem>
      </NForm>
    </NCard>

    <!-- Components Configuration -->
    <NCard title="组件样式" size="small">
      <NForm :show-label="true" label-placement="left" label-width="80px">
        <NFormItem label="按钮样式">
          <NSelect
            :value="localStyleConfig.components.buttonStyle"
            :options="buttonStyleOptions"
            @update:value="updateComponents({ buttonStyle: $event })"
          />
        </NFormItem>
        <NFormItem label="卡片高度">
          <NInputNumber
            :value="localStyleConfig.components.cardElevation"
            :min="0"
            :max="10"
            @update:value="updateComponents({ cardElevation: toUndefined($event) })"
          />
        </NFormItem>
        <NFormItem label="输入框样式">
          <NSelect
            :value="localStyleConfig.components.inputStyle"
            :options="inputStyleOptions"
            @update:value="updateComponents({ inputStyle: $event })"
          />
        </NFormItem>
      </NForm>
    </NCard>
  </NScrollbar>
</template>

<style scoped>
.style-configurator {
  height: 100%;
  overflow-y: auto;
}

:deep(.n-card__content) {
  padding: 4px;
}

:deep(.n-form-item) {
  margin-top: 0px;
  margin-bottom: 0px;
}

:deep(.n-form-item:last-child) {
  margin-bottom: 0;
}
</style>
